package com.zhz.elasticjob.config;

import com.dangdang.ddframe.job.api.simple.SimpleJob;
import com.dangdang.ddframe.job.config.JobCoreConfiguration;
import com.dangdang.ddframe.job.config.simple.SimpleJobConfiguration;
import com.dangdang.ddframe.job.lite.api.listener.ElasticJobListener;
import com.dangdang.ddframe.job.lite.api.strategy.JobShardingStrategy;
import com.dangdang.ddframe.job.lite.config.LiteJobConfiguration;
import com.dangdang.ddframe.job.lite.spring.api.SpringJobScheduler;
import com.dangdang.ddframe.job.reg.base.CoordinatorRegistryCenter;
import com.zhz.elasticjob.annotation.ElasticSimpleJob;
import lombok.SneakyThrows;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Configuration;

import javax.annotation.PostConstruct;
import java.util.Map;

/**
 * @program: schedule
 * @description: 简单作业, 配置bean
 * @author: zhanghz001
 * @create: 2021-08-05 09:58
 **/
@Configuration
//就是zookeeper的配置类需要配置
@ConditionalOnClass(CoordinatorRegistryCenter.class)
public class ElasticSimpleJobConfiguration {
    @Autowired
    private ApplicationContext applicationContext;
    
    @Autowired
    private CoordinatorRegistryCenter coordinatorRegistryCenter;
    
    @PostConstruct
    public void initSimpleJob() {
        // 获取spring容器中，标记有 @ElasticSimpleJob注解的Bean
        Map<String, Object> simpleJobMap =
                applicationContext.getBeansWithAnnotation(ElasticSimpleJob.class);
        
        // 1.判断Bean是否实现了SimpleJob接口
        for (String beanId : simpleJobMap.keySet()) {
            Object job = simpleJobMap.get(beanId);
            //需要是SimpleJob的实现,这个注解才有效
            if (job instanceof SimpleJob) {
                SimpleJob simpleJob = (SimpleJob) job;
                
                // 2.获取Bean上面@ElasticSimpleJob注解
                ElasticSimpleJob elasticSimpleJob = simpleJob.getClass().getAnnotation(ElasticSimpleJob.class);
                // 3.读取注解中的属性信息
                String cron = elasticSimpleJob.cron();
                String jobName = elasticSimpleJob.name();
                boolean overwrite = elasticSimpleJob.overwrite();
                Class<? extends JobShardingStrategy> jobShardingStrategy =
                        elasticSimpleJob.jobShardingStrategy();
                int shardingTotalCount = elasticSimpleJob.shardingTotalCount();
                
                boolean failover = elasticSimpleJob.failover();
                Class<? extends ElasticJobListener>[] listeners = elasticSimpleJob.listeners();
                boolean monitorExecution = elasticSimpleJob.monitorExecution();
                initSimpleJobBean(jobName,
                        cron,
                        shardingTotalCount,
                        failover,
                        overwrite,
                        jobShardingStrategy,
                        simpleJob,
                        listeners,
                        monitorExecution);
                
            }
            
        }
    }
    
    /**
     * //4.使用Java的API完成作业的配置和启动
     * 整合elastic-job的simpleJob的作业配置到spring的容器中
     *
     * @param jobName
     * @param cron
     * @param shardingTotalCount
     * @param failover
     * @param overwrite
     * @param jobShardingStrategy
     * @param simpleJob
     * @param listeners
     * @param monitorExecution
     */
    @SneakyThrows
    public void initSimpleJobBean(String jobName,
                                  String cron,
                                  int shardingTotalCount,
                                  boolean failover,
                                  boolean overwrite,
                                  Class<? extends JobShardingStrategy> jobShardingStrategy,
                                  SimpleJob simpleJob,
                                  Class<? extends ElasticJobListener>[] listeners,
                                  boolean monitorExecution) {
        // 定义作业核心配置
        JobCoreConfiguration simpleCoreConfig = JobCoreConfiguration.newBuilder(
                jobName,
                cron,
                shardingTotalCount
        )
                .failover(failover)
                .build();
        
        // 定义SIMPLE类型配置
        SimpleJobConfiguration simpleJobConfig = new SimpleJobConfiguration(
                simpleCoreConfig,
                //任务的全限定类名
                simpleJob.getClass().getCanonicalName()
        );
        
        // 定义Lite作业根配置
        LiteJobConfiguration simpleJobRootConfig = LiteJobConfiguration
                .newBuilder(simpleJobConfig)
                .overwrite(overwrite)
                .jobShardingStrategyClass(jobShardingStrategy.getCanonicalName())
                .monitorExecution(monitorExecution)
                
                .build();
        
        //把所有的类都实例化
        ElasticJobListener[] elasticJobListeners = new ElasticJobListener[listeners.length];
        for (int i = 0; i < listeners.length; i++) {
            Class<? extends ElasticJobListener> listener = listeners[i];
            elasticJobListeners[i] = listener.getConstructor().newInstance();
        }
        
        // 使用Java的API启动任务
        new SpringJobScheduler(simpleJob, coordinatorRegistryCenter,
                simpleJobRootConfig, elasticJobListeners)
                .init();
    }
}
